#include "PrecompiledHeaders.h"
#include "Pickup.h"
#include "Ball.h"
#include "FromString.h"
#include "BodyType.h"

Pickup::Pickup(Ogre::SceneNode *n, Ogre::String name, 
           Ogre::String bb_name, Ogre::String particle_name, Ogre::String col_ef_name,  
           OgreNewt::World *world, std::map<Ogre::String, Ogre::String> &params)
{
    node = n;
    collect_effect_name = col_ef_name;
    Ogre::Vector3 size(0.5, 0.5, 0.5);
    
    particles = addPickupParticles(node, name, particle_name);
    
    if (collect_effect_name.length() > 0)
    {
        
        collect_effect = addPickupParticles(node->getParentSceneNode()->createChildSceneNode(node->getPosition()), name + "_col", collect_effect_name);
        collect_effect->fastForward(rand() % 5);
        collect_effect->getEmitter(0)->setEmissionRate(0);
    }
    else
        collect_effect = NULL;
        
    if (bb_name.length() > 0)
    {
        addBillBoard(node, name + "_bb", bb_name);
    }
        
    collect_effect_active = false;
    
    body = addPickupBody(world, node, size);
    play_state = NULL;
    
    hide_pickup = false;
}

Ogre::ParticleSystem *Pickup::addPickupParticles(Ogre::SceneNode *pNode, Ogre::String name, Ogre::String templatename)
{
    Ogre::ParticleSystem *ps = pNode->getCreator()->createParticleSystem(name, templatename);
    pNode->attachObject(ps);
    return ps;
}

Ogre::BillboardSet *Pickup::addBillBoard(Ogre::SceneNode *pNode, Ogre::String name, Ogre::String bb_name)
{
    Ogre::BillboardSet *billboard_set = pNode->getCreator()->createBillboardSet(name, 1);
    
    billboard_set->setMaterialName(bb_name);
    billboard_set->setDefaultDimensions(1.5, 1.5);
    billboard_set->createBillboard(Ogre::Vector3::ZERO);
    
    pNode->attachObject(billboard_set);
    
    return billboard_set;
}

OgreNewt::Body *Pickup::addPickupBody(OgreNewt::World *world, Ogre::SceneNode *pNode, Ogre::Vector3&size)
{
    OgreNewt::Collision *col = new OgreNewt::CollisionPrimitives::Ellipsoid(world, size);
    OgreNewt::Body *body = new OgreNewt::Body(world, col);
    delete col;
    
    body->setPositionOrientation( pNode->getPosition(), pNode->getOrientation() );
    body->attachToNode( pNode );
    
    BodyType bt;
    bt.setSpecialType(BodyType::SP_PICKUP);
    body->setType(bt.getValue());
    
    Ogre::Real mass = 0;
    Ogre::Vector3 inertia = OgreNewt::MomentOfInertia::CalcEllipsoidSolid( mass, size );
    body->setMassMatrix( mass, inertia );
        
    return body;
}

void Pickup::animate(Ogre::Real time)
{
    if (collect_effect_active)
    {
        collect_effect_time += time;
        if (collect_effect_time > 0.1) {
            collect_effect_active = false;
            collect_effect->getEmitter(0)->setEmissionRate(0);
            if (hide_pickup)
                node->setVisible(false, false); 
        }
    }
}

void Pickup::apply(Player *pl)
{
    
    //node->setVisible(false, false);
    if (collect_effect) {
        collect_effect->getEmitter(0)->setEmissionRate(30);
        collect_effect_active = true;
        collect_effect_time = 0;
        if (pl->isMainPlayer())
            hide_pickup = true;
    }
    
        
}
    
void Pickup::reset()
{
    if (collect_effect_active) {
        collect_effect_active = false;
        collect_effect->getEmitter(0)->setEmissionRate(0);
    }
    node->setVisible(true, false);
    hide_pickup = false;
}

PowerUp::PowerUp(Ogre::SceneNode *node, Ogre::String name, Ogre::String bb_name,
                 OgreNewt::World *world, std::map<Ogre::String, Ogre::String> &params)
                    : Pickup(node, name, bb_name, "Pickup", "Pickup/CollectEffect", world, params)
{
    respawn = false;
    respawn_time = 0;
    active_time = DEFAULT_ACTIVE_TIME;
    
    std::map<Ogre::String, Ogre::String>::iterator it;
    
    it = params.find("respawn");
    if (it != params.end()) {
        from_string<Ogre::Real>( respawn_time, it->second.c_str(), std::dec);
        if (respawn_time > 0)
            respawn = true;
    }
    
    it = params.find("active_time");
    if (it != params.end())
        from_string<Ogre::Real>( active_time, it->second.c_str(), std::dec);
        
}

void LifePickup::apply(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_LIFEUP);
    Pickup::apply(pl);
    pl->getSession()->addLife();
    if (pl->isMainPlayer())
        play_state->updateLifeOverlay();
}

void TimePickup::apply(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_EXTRATIME);
    Pickup::apply(pl);
    if (pl->isMainPlayer())
        play_state->addTime(extra_time);
}

void SizePickup::apply(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_GROW);
    Pickup::apply(pl);
    pl->getBall()->increaseSize();
    if (pl->isMainPlayer())
        play_state->showSizeOverlay((int)body->getUserData());
}

void SizePickup::undo(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_SHRINK);
    pl->getBall()->decreaseSize();
    if (pl->isMainPlayer())
        play_state->hideSizeOverlay((int)body->getUserData());
}

void InvertPickup::apply(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_POWERDOWN);
    Pickup::apply(pl);
    pl->setInvert(true);
    if (pl->isMainPlayer())
        play_state->showInvertOverlay((int)body->getUserData());
}

void InvertPickup::undo(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_POWERDOWN_OFF);
    pl->setInvert(false);
    if (pl->isMainPlayer())
        play_state->hideInvertOverlay((int)body->getUserData());
}

void SpeedPickup::apply(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_POWERDOWN);
    Pickup::apply(pl);
    pl->setSpeed(true);
    if (pl->isMainPlayer())
        play_state->showSpeedOverlay((int)body->getUserData());
}

void SpeedPickup::undo(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_POWERDOWN_OFF);
    pl->setSpeed(false);
    if (pl->isMainPlayer())
        play_state->hideSpeedOverlay((int)body->getUserData());
}

void SensitivityPickup::apply(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_POWERDOWN);
    Pickup::apply(pl);
    pl->setSensitive(true);
    if (pl->isMainPlayer())
        play_state->showSensitivityOverlay((int)body->getUserData());
}

void SensitivityPickup::undo(Player *pl)
{
	play_state->getResources()->audio->playSource(AUDIO_POWERDOWN_OFF);
    pl->setSensitive(false);
    if (pl->isMainPlayer())
        play_state->hideSensitivityOverlay((int)body->getUserData());
}

ScorePickup::ScorePickup(Ogre::SceneNode *node, Ogre::String name, 
                         Ogre::String particle_name, Ogre::String c_eff_name, 
                         OgreNewt::World *world, std::map<Ogre::String, Ogre::String> &params, int a
                         )
                            : Pickup(node, name, "", particle_name, c_eff_name, world, params) {
    amount = a;
    animating = false;
    std::stringstream ss;
    ss << "+" << amount;
    Ogre::ColourValue colour = particles->getEmitter(0)->getColourRangeStart();
    text = new Ogre::MovableText(name + "_txt", ss.str(), "Quatron", 1, colour);
    text->setTextAlignment(Ogre::MovableText::H_CENTER, Ogre::MovableText::V_CENTER); // Center horizontally and display above the node
    //text->setAdditionalHeight( 2.0f ); //msg->setAdditionalHeight( ei.getRadius() )
    text_node = node->createChildSceneNode();
    text_node->attachObject(text);
    text_node->setVisible(false);
    
    /*
    Ogre::Animation* anim = mSceneMgr->createAnimation("an1", 14);
    anim->setInterpolationMode(Animation::IM_SPLINE);
    Ogre::NodeAnimationTrack* track = anim->createNodeTrack(1, animNode);
    Ogre::TransformKeyFrame* kf = track->createNodeKeyFrame(0);
    kf->setTranslate(Vector3(50,30,0));
    kf = track->createNodeKeyFrame(2);
    kf->setTranslate(Vector3(100, -30, 0));
    kf = track->createNodeKeyFrame(4);
    kf->setTranslate(Vector3(120, -100, 150));
    kf = track->createNodeKeyFrame(6);
    kf->setTranslate(Vector3(30, -100, 50));
    kf = track->createNodeKeyFrame(8);
    kf->setTranslate(Vector3(-50, 30, -50));
    kf = track->createNodeKeyFrame(10);
    kf->setTranslate(Vector3(-150, -20, -100));
    kf = track->createNodeKeyFrame(12);
    kf->setTranslate(Vector3(-50, -30, 0));
    kf = track->createNodeKeyFrame(14);
    kf->setTranslate(Vector3(50,30,0));
    */
    
}

void ScorePickup::reset() {
    Pickup::reset();
    animating = false;
    text_node->setVisible(false);
    text_node->setPosition(0, 0.75, 0);
    Ogre::ColourValue colour = text->getColor();
    colour.a = 0.8;
    text->setColor(colour);
}

void ScorePickup::animate(Ogre::Real time)
{
    Pickup::animate(time);
    if(animating) {
        text_node->translate(Ogre::Vector3(0, time * 2.5, 0));
        Ogre::ColourValue colour = text->getColor();
        colour.a *= 0.975;
        text->setColor(colour);
        if(colour.a < 0.05)
            text_node->setVisible(false);
    }
    // code to update animation here
}

void ScorePickup::apply(Player *pl)
{
    text_node->setVisible(true);
    animating = true;
    Pickup::apply(pl);
    pl->getSession()->addScore(amount);
    if (pl->isMainPlayer())
        play_state->updateScoreOverlay();
}

void ScorePickup1::apply(Player *pl)
{
	ScorePickup::apply(pl);
	play_state->getResources()->audio->playSource(AUDIO_COLLECT1);
}

void ScorePickup2::apply(Player *pl)
{
	ScorePickup::apply(pl);
	play_state->getResources()->audio->playSource(AUDIO_COLLECT2);

}

void ScorePickup3::apply(Player *pl)
{
	ScorePickup::apply(pl);
	play_state->getResources()->audio->playSource(AUDIO_COLLECT3);
}

